package com.liaoyifan.core.util;

import java.util.Objects;

/** 用于ASCII大小写格式之间的转换工具类，支持连字符式、下划线式和驼峰式等格式转换。 非ASCII输入的行为未定义。 */
public enum CaseFormat {
    /** 连字符命名格式，例如 "lower-hyphen" */
    LOWER_HYPHEN("-") {
        @Override
        boolean isWordBoundary(char c) {
            return c == '-';
        }

        @Override
        String normalizeWord(String word) {
            return toAsciiLowerCase(word);
        }

        @Override
        String convert(CaseFormat target, String s) {
            if (target == LOWER_UNDERSCORE) {
                return s.replace('-', '_');
            }
            if (target == UPPER_UNDERSCORE) {
                return toAsciiUpperCase(s.replace('-', '_'));
            }
            return super.convert(target, s);
        }
    },

    /** 下划线命名格式（小写），例如 "lower_underscore" */
    LOWER_UNDERSCORE("_") {
        @Override
        boolean isWordBoundary(char c) {
            return c == '_';
        }

        @Override
        String normalizeWord(String word) {
            return toAsciiLowerCase(word);
        }

        @Override
        String convert(CaseFormat target, String s) {
            if (target == LOWER_HYPHEN) {
                return s.replace('_', '-');
            }
            if (target == UPPER_UNDERSCORE) {
                return toAsciiUpperCase(s);
            }
            return super.convert(target, s);
        }
    },

    /** 驼峰命名格式（首字母小写），例如 "lowerCamel" */
    LOWER_CAMEL("") {
        @Override
        boolean isWordBoundary(char c) {
            return c >= 'A' && c <= 'Z';
        }

        @Override
        String normalizeWord(String word) {
            return firstCharToUpperRestLower(word);
        }
    },

    /** 驼峰命名格式（首字母大写），例如 "UpperCamel" */
    UPPER_CAMEL("") {
        @Override
        boolean isWordBoundary(char c) {
            return c >= 'A' && c <= 'Z';
        }

        @Override
        String normalizeWord(String word) {
            return firstCharToUpperRestLower(word);
        }
    },

    /** 下划线命名格式（大写），例如 "UPPER_UNDERSCORE" */
    UPPER_UNDERSCORE("_") {
        @Override
        boolean isWordBoundary(char c) {
            return c == '_';
        }

        @Override
        String normalizeWord(String word) {
            return toAsciiUpperCase(word);
        }

        @Override
        String convert(CaseFormat target, String s) {
            if (target == LOWER_HYPHEN) {
                return toAsciiLowerCase(s.replace('_', '-'));
            }
            if (target == LOWER_UNDERSCORE) {
                return toAsciiLowerCase(s);
            }
            return super.convert(target, s);
        }
    };

    final String wordSeparator;

    CaseFormat(String wordSeparator) {
        this.wordSeparator = wordSeparator;
    }

    /** 判断字符是否为单词边界 */
    abstract boolean isWordBoundary(char c);

    /** 规范化单词（处理大小写） */
    abstract String normalizeWord(String word);

    /** 将当前格式的字符串转换为目标格式 */
    public final String to(CaseFormat target, String str) {
        Objects.requireNonNull(target, "目标格式不能为null");
        Objects.requireNonNull(str, "输入字符串不能为null");
        return (target == this) ? str : convert(target, str);
    }

    /** 转换逻辑的核心实现 */
    String convert(CaseFormat target, String s) {
        StringBuilder result = null;
        int start = 0;
        int length = s.length();

        for (int end = 0; end < length; end++) {
            if (isWordBoundary(s.charAt(end))) {
                if (result == null) {
                    // 初始化缓冲区，预留额外空间用于分隔符
                    result = new StringBuilder(length + 4 * target.wordSeparator.length());
                }
                // 处理当前单词
                processWord(target, s, start, end, result, start == 0);
                // 添加目标格式的分隔符
                result.append(target.wordSeparator);
                start = end + 1; // 跳过边界字符
            }
        }

        // 处理最后一个单词
        if (result == null) {
            // 没有找到边界，整个字符串作为一个单词
            return target.normalizeFirstWord(s);
        } else {
            processWord(target, s, start, length, result, start == 0);
            return result.toString();
        }
    }

    /** 处理单个单词并添加到结果缓冲区 */
    private void processWord(
            CaseFormat target,
            String s,
            int start,
            int end,
            StringBuilder result,
            boolean isFirstWord) {
        if (start >= end) {
            return; // 空单词不处理
        }
        String word = s.substring(start, end);
        result.append(isFirstWord ? target.normalizeFirstWord(word) : target.normalizeWord(word));
    }

    /** 规范化第一个单词（特殊处理LOWER_CAMEL的第一个单词） */
    private String normalizeFirstWord(String word) {
        return (this == LOWER_CAMEL) ? toAsciiLowerCase(word) : normalizeWord(word);
    }

    /** 创建一个转换器，用于在当前格式和目标格式之间双向转换 */
    public StringConverter converterTo(CaseFormat target) {
        return new StringConverter(this, target);
    }

    /** 字符串转换器，支持正向和反向转换 */
    public static class StringConverter {
        private final CaseFormat source;
        private final CaseFormat target;

        StringConverter(CaseFormat source, CaseFormat target) {
            this.source = Objects.requireNonNull(source);
            this.target = Objects.requireNonNull(target);
        }

        /** 正向转换：从源格式到目标格式 */
        public String convert(String s) {
            return source.to(target, s);
        }

        /** 反向转换：从目标格式到源格式 */
        public String reverseConvert(String s) {
            return target.to(source, s);
        }
    }

    /** 将字符串转换为ASCII大写 */
    private static String toAsciiUpperCase(String s) {
        int length = s.length();
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(toAsciiUpper(s.charAt(i)));
        }
        return sb.toString();
    }

    /** 将字符串转换为ASCII小写 */
    private static String toAsciiLowerCase(String s) {
        int length = s.length();
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(toAsciiLower(s.charAt(i)));
        }
        return sb.toString();
    }

    /** 将字符转换为ASCII大写（仅处理a-z） */
    private static char toAsciiUpper(char c) {
        return (c >= 'a' && c <= 'z') ? (char) (c - 32) : c;
    }

    /** 将字符转换为ASCII小写（仅处理A-Z） */
    private static char toAsciiLower(char c) {
        return (c >= 'A' && c <= 'Z') ? (char) (c + 32) : c;
    }

    /** 首字母大写，其余小写（仅处理ASCII） */
    private static String firstCharToUpperRestLower(String word) {
        if (word.isEmpty()) {
            return word;
        }
        char firstChar = word.charAt(0);
        String rest = word.substring(1);
        return toAsciiUpper(firstChar) + toAsciiLowerCase(rest);
    }
}
